import re


class LineType(object):
    """Classe abstrata de uma linha."""
    def toString(self):
        """Retorna uma string contendo a linha."""
        raise Exception('Implements toString function in child class.')




class CommentLine(LineType):
    """Linha do tipo comentario."""
    regex = re.compile(r'^\s*\#(?P<comment>.*)\s*$')
    
    def __init__(self, comment):
        self.comment = comment
    
    
    def toString(self):
        """Retorna uma string contendo a linha."""
        return '#' + self.comment
    
    
    def parse(cls, line):
        """Tenta analizar a linha como uma CommentLine, caso
        nao seja compativel com o formato retorna None, se
        compativel retorna uma instancia de CommentLine."""
        mt = cls.regex.match(line)
        if mt is None:
            return None
        return cls(mt.group('comment'))
    
    parse = classmethod(parse)




class SectionLine(LineType):
    """Linha de cabecalho."""
    regex = re.compile(r'^\s*\['
                       r'(?P<name>[^]]+)'
                       r'\]\s*'
                       r'(|\#\s*(?P<comment>.*))'
                       r'\s*$')
    
    def __init__(self, name, comment=None):
        self.name = name
        self.comment = comment
    
    
    def toString(self):
        """Retorna uma string contendo a linha."""
        basic = '[' + self.name + ']'
        if self.comment is not None:
            return basic + ' #' + self.comment
        return basic
    
    
    def parse(cls, line):
        """Tenta analizar a linha como um SectionLine, caso
        nao seja compativel com o formato retorna None, se
        compativel retorna uma instancia de SectionLine."""
        mt = cls.regex.match(line)
        if mt is None:
            return None
        return cls(mt.group('name'), mt.group('comment'))
    
    parse = classmethod(parse)




class OptionLine(LineType):
    """Linha de opcao."""
    regex = re.compile(r'^\s*'
                       r'(?P<key>[^=]+)'
                       r'\s*=\s*'
                       r'(?P<value>[^#]*)'
                       r'(|\#\s*(?P<comment>.*))'
                       r'\s*$')
    
    def __init__(self, key, value, comment=None):
        self.key = key
        self.value = value.strip()
        self.comment = comment
    
    
    def toString(self):
        """Retorna uma string contendo a linha."""
        basic = self.key + '=' + self.value
        if self.comment is not None:
            return basic + ' #' + self.comment
        return basic
    
    
    def parse(cls, line):
        """Tenta analizar a linha como uma OptionLine, caso
        nao seja compativel com o formato retorna None, se
        compativel retorna uma instancia de OptionLine."""
        mt = cls.regex.match(line)
        if mt is None:
            return None
        return cls(mt.group('key'), mt.group('value'), mt.group('comment'))
    
    parse = classmethod(parse)




class BlankLine(LineType):
    """Linha em branca."""
    
    def toString(self):
        """Retorna uma string contendo a linha."""
        return ''
    
    
    def parse(cls, line):
        """Tenta analizar a linha como uma BlankLine, caso
        nao seja compativel com o formato retorna None, se
        compativel retorna uma instancia de BlankLine."""
        if line.strip():
            return None
        return cls()
    
    parse = classmethod(parse)




class UndefinedLine(LineType):
    """Linha que nao pertence a um tipo definido."""
    def __init__(self, line):
        self.line = line
    
    
    def toString(self):
        """Retorna uma string contendo a linha."""
        return self.line
